﻿namespace TestApp.Tests
{
    using System;
    using System.Collections.Generic;
    using Contracts;
    using DataService;
    using Moq;
    using NUnit.Framework;
    using Shouldly;

    [TestFixture]
    internal class DataServiceFixture
    {
        private readonly List<Mock<IDataSender>> _dataSenders = new List<Mock<IDataSender>>();
        private Mock<ICallbackProvider<IDataServiceCallback>> _callbackProvider;
        private Mock<IDataServiceCallback> _callback;
        private Mock<ISimpleLogger> _logger;

        [SetUp]
        public void SetUp()
        {
            _logger = new Mock<ISimpleLogger>();
            _dataSenders.Clear();
            _callback = new Mock<IDataServiceCallback>();
            _callbackProvider = new Mock<ICallbackProvider<IDataServiceCallback>>();
            _callbackProvider.Setup(i => i.GetCallback()).Returns(_callback.Object);
        }

        [Test]
        public void ShouldCreateAndInitializeDataSenderWhenSubscribe()
        {
            // Given
            var target = CreateInstance();

            // When
            target.SubscribeToAll();
            target.Subscribe(1);

            // Then
            _dataSenders.Count.ShouldBe(2);
            _dataSenders[0].Verify(i => i.Initialize(It.IsAny<IDisposable>(), _callback.Object, null));
            _dataSenders[1].Verify(i => i.Initialize(It.IsAny<IDisposable>(), _callback.Object, 1));
        }

        [Test]
        public void ShouldDisposeDataSenderWhenUnsubscribe()
        {
            // Given
            var target = CreateInstance();
            target.SubscribeToAll();
            var subscription1 = target.SubscribeToAll();
            var subscription2 = target.Subscribe(1);

            // When
            target.Unsubscribe(subscription1);
            target.Unsubscribe(subscription2);

            // Then
            _dataSenders.Count.ShouldBe(1);
        }

        private IDataService CreateInstance()
        {
            return new DataService(
                _callbackProvider.Object,
                () =>
                {
                    var dataSender = new Mock<IDataSender>();
                    _dataSenders.Add(dataSender);
                    dataSender.Setup(i => i.Dispose()).Callback(() => _dataSenders.Remove(dataSender));
                    return dataSender.Object;
                },
                _logger.Object);
        }
    }
}
